import glob
from http.server import BaseHTTPRequestHandler,ThreadingHTTPServer
import json
from datetime import datetime
import math
import sqlite3
import gv
from urllib.parse import urlparse, parse_qs
import os

class RequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        # 解析self.path以获取查询字符串
        parsed_path = urlparse(self.path)
        query = parsed_path.query
        
        # 使用parse_qs解析查询字符串，得到一个字典
        # 请注意，parse_qs返回的字典中的值是列表，因为一个参数可能有多个值
        params = parse_qs(query)
        
        # 要每个参数只有一个值，而不是列表：
        # 将列表转换为单个值（如果列表中有多个值，将使用第一个值）
        params = {k: v[0] for k, v in params.items()}
        
        self.r={
            'code': 200,
            'msg': 'ok',
            'data': {},
            'error': ''
        }
        
        if self.path == '/ping':
            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            # self.send_header('Connection', 'close')
            self.end_headers()
            # 把 self.r 发送出去
            self.wfile.write(json.dumps(self.r).encode())

        elif self.path == '/favicon.ico':
            try:
                self.send_response(200)
                self.send_header('Content-type', 'image/x-icon')
                with open('favicon.ico', 'rb') as f:
                    favicon = f.read()  # 读取文件内容
                    self.send_header('Content-Length', len(favicon))
                    self.end_headers()
                    self.wfile.write(favicon)  # 发送文件内容
            except IOError as e:
                print(f"Error reading favicon.ico: {e}")
                self.send_response(404)  # 如果文件不存在，发送404响应
            except Exception as e:
                print(f"An unexpected error occurred: {e}")
                self.send_response(500)  # 发送500内部服务器错误响应
            
        elif self.path.startswith('/programes'): # 获取列表
            try:
                # 使用get方法获取键的值，如果键不存在，则返回默认值
                program = params.get('program', '')
                page = params.get('page', 1)
                pagesize = params.get('pagesize', 20)
                
                # 获取 .db/ 下的  包含 program 的全部文件，只要文件名
                files = [f[5:-3] for f in glob.glob(f'./db/*{program}*.db') if program in f]
                
                self.r['data']['total']=len(files)
                
                files.sort(reverse=True)
                if page == 1:
                    files = files[:int(pagesize)]
                else:
                    files = files[int(pagesize)*(int(page)-1):int(pagesize)*int(page)]
                self.r['data']['page']=page
                self.r['data']['pages'] = math.ceil(self.r['data']['total']/int(pagesize))
                self.r['data']['pagesize']=pagesize
                self.r['data']['files']=files
                self.r['data']['program']=program
                self.send_response(200)
                self.send_header('Content-type', 'application/json')
                self.end_headers()
                self.wfile.write(json.dumps(self.r).encode())
                
            except Exception as e:  # 捕获其他所有异常
                self.send_response(500)  # 发送500 Internal Server Error响应
                self.end_headers()
                print(f"An unexpected error occurred: {e}")
        elif self.path.startswith("/programe"):  # 获取详情
            try:
                program = params.get('program', '')
                program = gv.sanitize_name(program)
                fullname = "./db/"+program+".db"
                if not program.strip() or not os.path.exists(fullname): # 没有输入program名，或者没有这个文件
                    raise FileNotFoundError()
                conn = sqlite3.connect(fullname)
                c = conn.cursor()
                c.execute("select programname,errornum from programname limit 1")
                program = c.fetchone()
                
                c.execute("select BlockNo_InspectType,ng from sample")
                samples = c.fetchall()
                
                self.send_response(200)
                self.send_header('Content-type', 'application/json')
                # 说明相应内容是 utf8 编码
                self.send_header('Content-Encoding', 'utf-8') 
                self.end_headers()
                self.r['data']['progame_borad']=program[0]
                self.r['data']['公差数']=program[1]
                for sample in samples:
                    self.r['data'][sample[0]]=sample[1]
                    
                self.wfile.write(json.dumps(self.r).encode())
                
            except FileNotFoundError:
                self.send_response(404)
                self.send_header('Content-type', 'text/plain')
                self.end_headers()
                self.r['code'] = 404
                self.r['msg'] = '没找到'+program
                self.wfile.write(json.dumps(self.r).encode())
            except Exception as e:  # 捕获其他所有异常
                self.send_response(500)  # 发送500 Internal Server Error响应
                self.end_headers()
                self.r['code'] = 500
                self.r['msg'] = '服务器内部错误:'+str(e)
                self.wfile.write(json.dumps(self.r).encode())
                print(f"An unexpected error occurred: {e}")
                
        elif self.path.startswith("/delete"):  #删除指定文件
            try:
                program = params.get('program', '')
                program = gv.sanitize_name(program)
                fullname = "./db/"+program+".db"
                if not program.strip() or not os.path.exists(fullname): # 没有输入program名，或者没有这个文件
                    raise FileNotFoundError()
                else:
                    os.remove(fullname)
                
                self.r['code'] = 200
                self.r['msg'] = '删除成功：'+program
                self.send_response(200)
                self.send_header('Content-type', 'application/json')
                self.end_headers()
                self.wfile.write(json.dumps(self.r).encode())
                
            except FileNotFoundError:
                self.send_response(404)
                self.end_headers()
                self.r['code'] = 404
                self.r['msg'] = '没找到'+program
                self.wfile.write(json.dumps(self.r).encode())
                
            except Exception as ex:
                self.send_response(500)  # 发送500 Internal Server Error响应
                self.end_headers()
                self.r['code'] = 500
                self.r['msg'] = '服务器内部错误:'+str(ex)
                self.wfile.write(json.dumps(self.r).encode())
                
        elif self.path.startswith("/new"):  
            gv.sample_event.set()
            # 获取当前用户的ip
            gv.logServerIp = self.client_address[0]
            gv.totalErrors = params['tolerance']
            gv.q.put(f"sample:要求新增标准,公差数：{gv.totalErrors}")
            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.send_header('Connection', 'close')
            self.end_headers()
            self.r['msg'] = "收到请求,公差："+params['tolerance']
            self.wfile.write(json.dumps(self.r).encode())
        elif self.path.startswith("/compare"):  
            # 获取当前用户的ip
            gv.logServerIp = self.client_address[0]
            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.send_header('Connection', 'close')
            self.end_headers()
            self.r['msg'] = "收到请求,对比："+params['program']
            self.wfile.write(json.dumps(self.r).encode())
            gv.compare_event.set()
            gv.sample_name = params['program']
            gv.q.put(f"compare:对比标准：{gv.sample_name}")
        elif self.path.startswith('/edit'):
            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.send_header('Connection', 'close')
            self.end_headers()
            programname = params['program']
            programname = gv.sanitize_name(programname)
            fullname = "./db/" + programname + ".db"
            if not os.path.exists(fullname):
                self.r['msg'] = "没有这个样本文件："+programname
                self.wfile.write(json.dumps(self.r).encode())
                return 
            try:
                conn = sqlite3.connect(fullname)
                c = conn.cursor()
                c.execute("update programname set errornum=? where programname=?",(params['tolerance'],params['program']))
                conn.commit()
                c.close()
                conn.close()
                self.r['msg'] = "修改"+params['program']+"的公差为"+params['tolerance']
                self.wfile.write(json.dumps(self.r).encode())
            except Exception as e:  # 捕获其他所有异常
                self.send_response(500)  # 发送500 Internal Server Error响应
                self.end_headers()
                self.r['code'] = 500
                self.r['msg'] = '服务器内部错误:'+str(e)
                self.wfile.write(json.dumps(self.r).encode())
        else:             
            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            # 获取当前时间
            t = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            # 获取用户的ip
            client_ip = self.client_address[0]
            r = t + " : " + client_ip
            self.send_header('Connection', 'close')
            self.end_headers()
            self.r['msg'] = r
            self.wfile.write(json.dumps(self.r).encode())
        
        self.wfile.close()
        return 
            
    def do_POST(self):
        if self.path == '/file':
            # 读取请求体中的内容
            content_length = int(self.headers['Content-Length'])
            post_data = self.rfile.read(content_length)
            
            # 解析JSON数据
            try:
                data = json.loads(post_data.decode('utf-8'))
            except json.JSONDecodeError:
                self.send_error(400, "Invalid JSON format")
                return
            
            # 这里可以对data进行处理，然后生成txt文件的内容
            txt_content = "Received data: " + str(data)
            
            # 设置响应
            self.send_response(200)
            self.send_header('Content-type', 'text/plain')
            self.end_headers()
            
            # 发送txt文件内容
            self.wfile.write(txt_content.encode('utf-8'))
            
        elif self.path=='/query':
            # 设置响应
            self.send_response(200)
            self.send_header('Content-type', 'text/plain')
            self.end_headers()
            self.wfile.write("test test".encode('utf-8'))
        else:
            self.send_error(404, "File not found")

def runWerServer(server_class=ThreadingHTTPServer, handler_class=RequestHandler, port=8080):
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    # print(f"Starting httpd server on port {port}")
    httpd.log = None  # 设置日志为 None 以关闭日志输出
    httpd.serve_forever()


if __name__ == '__main__':
    runWerServer()


# curl -X POST -H "Content-Type: application/json" -d "{'your_key': 'your_value'}" http://localhost:8080/query
# curl -X POST -H "Content-Type: application/json" -d '{"your_key": "your_value"}' http://localhost:8080/query